package com.florent37.runtime_permission_rx;

import com.florent37.runtime_permission.PermissionResult;
import com.florent37.runtime_permission.RuntimePermission;
import com.florent37.runtime_permission.callbacks.ResponseCallback;
import io.reactivex.*;
import ohos.aafwk.ability.fraction.Fraction;
import ohos.aafwk.ability.fraction.FractionAbility;

import java.util.Arrays;
import java.util.List;


public class RxPermissions {
    private final RuntimePermission runtimePermission;

    public RxPermissions(final FractionAbility ability) {
        runtimePermission = RuntimePermission.askPermission(ability);
    }

    public RxPermissions(final Fraction fraction) {
        runtimePermission = RuntimePermission.askPermission(fraction.getFractionAbility());
    }

    public Observable<PermissionResult> request(final List<String> permissions){
        return Observable.create(new ObservableOnSubscribe<PermissionResult>() {
            @Override
            public void subscribe(final ObservableEmitter<PermissionResult> emitter) throws Exception {
                runtimePermission
                        .request(permissions)
                        .onResponse(new ResponseCallback() {
                            @Override
                            public void onResponse(PermissionResult result) {
                                if(result.isAccepted()){
                                    emitter.onNext(result);
                                    emitter.onComplete();
                                }else {
                                    emitter.onError(new Error(result));
                                }
                            }
                        }).ask();

            }
        });
    }

    /**
     * use only request with an empty array to request all manifest permissions
     */
    public Observable<PermissionResult> request(String... permissions) {
        return request(Arrays.asList(permissions));
    }

    /**
     * use only request with an empty array to request all manifest permissions
     */
    public Single<PermissionResult> requestAsSingle(final String... permissions) {
        return requestAsSingle(Arrays.asList(permissions));
    }

    public Single<PermissionResult> requestAsSingle(final List<String> permissions) {
        return Single.create(new SingleOnSubscribe<PermissionResult>() {
            @Override
            public void subscribe(final SingleEmitter<PermissionResult> emitter) throws Exception {
                runtimePermission
                        .request(permissions)
                        .onResponse(new ResponseCallback() {
                            @Override
                            public void onResponse(PermissionResult result) {
                                if (result.isAccepted()) {
                                    emitter.onSuccess(result);
                                } else {
                                    emitter.onError(new Error(result));
                                }
                            }
                        }).ask();
            }
        });
    }

    public Flowable<PermissionResult> requestAsFlowable(String... permissions) {
        return requestAsFlowable(Arrays.asList(permissions));
    }

    public Flowable<PermissionResult> requestAsFlowable(final List<String> permissions) {
        return Flowable.create(new FlowableOnSubscribe<PermissionResult>() {
            @Override
            public void subscribe(final FlowableEmitter<PermissionResult> emitter) throws Exception {
                runtimePermission
                        .request(permissions)
                        .onResponse(new ResponseCallback() {
                            @Override
                            public void onResponse(PermissionResult result) {
                                if (result.isAccepted()) {
                                    emitter.onNext(result);
                                } else {
                                    emitter.onError(new Error(result));
                                }
                            }
                        }).ask();
            }
        }, BackpressureStrategy.LATEST);
    }

    public Maybe<PermissionResult> requestAsMaybe(String... permissions) {
        return requestAsMaybe(Arrays.asList(permissions));
    }

    public Maybe<PermissionResult> requestAsMaybe(final List<String> permissions) {
        return Maybe.create(new MaybeOnSubscribe<PermissionResult>() {
            @Override
            public void subscribe(final MaybeEmitter<PermissionResult> emitter) throws Exception {
                runtimePermission
                        .request(permissions)
                        .onResponse(new ResponseCallback() {
                            @Override
                            public void onResponse(PermissionResult result) {
                                if (result.isAccepted()) {
                                    emitter.onSuccess(result);
                                } else {
                                    emitter.onError(new Error(result));
                                }
                            }
                        }).ask();
            }
        });
    }

    public static class Error extends Throwable {
        private final PermissionResult result;

        private Error(PermissionResult result) {
            this.result = result;
        }

        public PermissionResult getResult() {
            return result;
        }
    }
}
